import 'dart:convert';
import 'dart:io';
import 'package:architecture/ext_string.dart';
import 'package:architecture/log.dart';
import 'package:dio/dio.dart';
import 'package:dio/dio.dart' as dio;
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:study_demo/api/api.dart';
import 'package:study_demo/api/bean.dart';
import 'package:study_demo/api/status_code.dart';
import 'package:toast/toast.dart';
import 'package:study_demo/util/extension.dart';

import '../base/BaseController.dart';

const String downUrl = 'http://app.izis.cn:8080/GoWebService/YzGoPlat.apk';
const String baseUrlTest = 'http://app.izis.cn:8080/GoWebService/';

typedef Success = Function(dynamic data);
typedef SuccessPlus = Function(dynamic data, int statusCode);
typedef Error = Function(String msg);

Net api = Net.instance;

class Net {
  static Net? _instance;

  static Net get instance => _getInstance();

//  factory Net() => _getInstance();

  static Net _getInstance() {
    if (_instance == null) _instance = Net._();
    return _instance!;
  }

  late dio.Dio _dio;
  bool _loading = true;
  String loadingMsg = 'loading'.tr;

  Net._() {
    _dio = dio.Dio(dio.BaseOptions(
      connectTimeout: Duration(milliseconds: 15000),
    ));
    _dio.interceptors
      ..add(dio.InterceptorsWrapper(
        onRequest: (requestOptions, handler) {
          if (_loading) Get.loading(message: loadingMsg);
          return handler.next(requestOptions);
        },
        onResponse: (response, handler) {
          if (_loading) {
            Get.dismiss();
          }
          return handler.next(response);
        },
        onError: (dioError, handler) {
          if (_loading) {
            Get.dismiss();
          }

          return handler.next(dioError);
        },
      ))
      ..add(dio.LogInterceptor(requestBody: true, responseBody: true));
  }

  void get(RequestModel requestModel,
      {Success? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio.post(base_url2, data: requestModel.toJson()).then(
      (response) {
        if (response.statusCode == 200) {
          var responseModel = ResponseModel.fromJson(response.data);
          if (responseModel.error == 0) {
            dynamic data;
            if (responseModel.data is String) {
              try {
                data = json.decode(responseModel.data as String);
              } catch (e) {
                data = responseModel.data;
              }
            } else {
              data = responseModel.data;
            }
            print(data);
            if (success != null) {
              success(data);
            }
          } else {
            if (error != null) {
              error(responseModel.msg!);
            }
          }
        } else {
          if (error != null) {
            error("${response.statusCode}");
          }
        }
      },
    ).onError((e, stackTrace) {
      // Get.find<Logger>().e(e);
      if (error != null) {
        error("$e");
        Toast.show('net_connect_timeout'.tr, textStyle: Get.overlayContext);
      }
    });
  }

  void getYz(RequestModel requestModel, String url,
      {SuccessPlus? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio
        .post(url + "getdataserver", data: requestModel.toJson())
        .then((response) {
      // if (response.statusCode == 200) {
      Log.d('data:${response.toString()}');
      String data = response.toString();
      int index = data.indexOf('\"data\"');
      data = data.substring(index + 7, data.length - 1);
      // var responseModel = ResponseModel.fromJson(response.data);
      // if (responseModel.error == 0) {
      //   dynamic data;
      //   if (responseModel.data is String) {
      //     try {
      //       data = json.decode(responseModel.data as String);
      //     } catch (e) {
      //       data = responseModel.data;
      //     }
      //   } else {
      //     data = responseModel.data;
      //   }
      print(data);
      if (success != null) {
        success(data, response.statusCode!);
      }
      // } else {
      // if (error != null) {
      //   error(responseModel.msg!);
      // }
      // }
      // } else {
      //   if (error != null) {
      //     error("${response.statusCode}");
      //   }
      // }
      //   },
      // ).onError((e, stackTrace) {
      //   Get.find<Logger>().e(e);
      //   if (error != null) {
      //     error("$e");
      //     Toast.show('net_connect_timeout'.tr, textStyle: Get.overlayContext);
      //   }
    });
  }

  void post(RequestModel requestModel,
      {Success? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio.post(base_url3, data: requestModel.toJson()).then(
      (response) {
        if (response.statusCode == 200) {
          var responseModel = ResponseModel.fromJson(response.data);
          if (responseModel.error == 0) {
            if (responseModel.data == null) {
              responseModel.data = "1";
            }
            var entryJson = json.decode(responseModel.data);
            if (success != null) {
              success(entryJson);
            }
          } else {
            if (error != null) {
              error(responseModel.msg!);
            }
          }
        } else {
          if (error != null) {
            error("${response.statusCode}");
          }
        }
      },
    ).onError((e, stackTrace) {
      // Toast.show('net_connect_timeout'.tr, textStyle: Get.overlayContext);
      if (error != null) {
        error("$e");
      }
    });
  }

  void getYzPlus(RequestModel requestModel,
      {Success? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio
        .post(yz_url + "GoWebService/getdataserver",
            data: requestModel.toJson())
        .then(
      (response) {
        if (response.statusCode == 200) {
          // print(
          //     '请求地址：${BASE_URL}GoWebService/getdataserver code:${requestModel.code} 返回数据：${response.data}');
          var responseModel = ResponseModel.fromJson(response.data);
          if (responseModel.error == 0) {
            dynamic data;
            if (responseModel.data is String) {
              try {
                data = json.decode(responseModel.data);
              } catch (e) {
                data = responseModel.data;
              }
            } else {
              data = responseModel.data;
            }
            print(data);
            if (success != null) {
              success(data);
            }
          } else {
            if (error != null) {
              error(responseModel.msg!);
            }
          }
        } else {
          if (error != null) {
            error("${response.statusCode}");
          }
        }
      },
    ).onError((e, stackTrace) {
      Get.find<Logger>().e(e);
      if (error != null) {
        // error("$e");
        toast('net_connect_timeout'.translate());
      }
    });
  }

  void getYzSE(RequestModel requestModel,
      {Success? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio.post(yz_se_url + "getdataserver", data: requestModel.toJson()).then(
      (response) {
        if (response.statusCode == 200) {
          // print(
          //     '请求地址：${BASE_URL}GoWebService/getdataserver code:${requestModel.code} 返回数据：${response.data}');
          var responseModel = ResponseModel.fromJson(response.data);
          if (responseModel.error == 0) {
            dynamic data;
            if (responseModel.data is String) {
              try {
                data = json.decode(responseModel.data);
              } catch (e) {
                data = responseModel.data;
              }
            } else {
              data = responseModel.data;
            }
            print(data);
            if (success != null) {
              success(data);
            }
          } else {
            if (error != null) {
              error(responseModel.msg!);
            }
          }
        } else {
          if (error != null) {
            error("${response.statusCode}");
          }
        }
      },
    ).onError((e, stackTrace) {
      Get.find<Logger>().e(e);
      if (error != null) {
        // error("$e");
        toast('net_connect_timeout'.translate());
      }
    });
  }

  void getYzSEPlus(String token, String url, Map<String, dynamic> map,
      {Success? success, Error? error, bool loading = true}) async {
    Options options = Options();
    Map<String, dynamic>? headers = {};
    headers["token"] = token;
    options.headers = headers;
    _loading = loading;
    _dio
        .get(baseUrl + url, queryParameters: map, options: options)
        .then((response) {
      int code = response.data['code'];
      if (code == SUCCESS) {
        var body = response.data['body'];
        if (success != null) {
          Get.dismiss();
          success(body);
        }
      } else {
        if (error != null) {
          error(response.data['message']);
        }
      }
    }).onError((e, stackTrace) {
      if (error != null) {
        error('net_error'.tr);
      }
    });
  }

  Future getAIStep(RequestModel requestModel,
      {int type = 0, bool showLoadingUI = true}) async {
    var port = 8110;
    switch (type) {
      case 0:
      case 1:
        port = 7000;
        break;
      case 2:
        port = 7009;
        break;
      case 3:
        port = 7013;
        break;
      case 4:
        port = 8110;
        break;
      case 5:
        port = 8111;
        break;
      case 6:
        port = 8112;
        break;
      case 7:
        port = 8120;
        break;
    }
    try {
      if (showLoadingUI) {
        Get.loading(message: 'loading'.translate());
      }

      var response = await _dio.post(
        "http://golaxy.izis.cn:$port/genmoves",
        data: requestModel.toJson(),
      );
      if (response.statusCode == 200) {
        return response;
      } else {
        return Future.error("${response.statusCode}");
      }
    } catch (e) {
      return Future.error(e);
    } finally {
      if (showLoadingUI) {
        Get.dismiss();
      }
    }
  }

  void getAI(RequestModel requestModel,
      {Success? success, Error? error, bool loading = true}) async {
    this._loading = loading;
    _dio
        .post("http://golaxy.izis.cn:8110/genmoves",
            data: requestModel.toJson())
        .then(
      (response) {
        if (response.statusCode == 200) {
          var responseModel = ResponseModel.fromJson(response.data);
          if (responseModel.error == 0) {
            var entryJson = json.decode(responseModel.data);
            if (success != null) {
              success(entryJson);
            }
          } else {
            if (error != null) {
              error(responseModel.msg!);
            }
          }
        } else {
          if (error != null) {
            error("${response.statusCode}");
          }
        }
      },
    ).onError((e, stackTrace) {
      if (error != null) {
        error("$e");
      }
    });
  }

  Future getAICountResult(RequestModel requestModel,
      {bool showLoadingUI = true, int boardSize = 19}) async {
    var port = 8110;
    switch (boardSize) {}
    try {
      if (showLoadingUI) {
        Get.loading(message: 'loading'.translate());
      }

      var response = await _dio.post(
        "http://golaxy.izis.cn:$port/genmoves",
        data: requestModel.toJson(),
      );

      if (response.statusCode == 200) {
        var responseModel = ResponseModel.fromJson(response.data);
        if (responseModel.error == 0) {
          var data = json.decode(responseModel.data);
          return data;
        } else {
          return Future.error(responseModel.msg!);
        }
      } else {
        return Future.error("${response.statusCode}");
      }
    } catch (e) {
      return Future.error(e);
    } finally {
      if (showLoadingUI) {
        Get.dismiss();
      }
    }
  }

  Future getTest(RequestModel requestModel, {bool showLoadingUI = true}) async {
    try {
      var response = await _dio.post(
        baseUrlTest + "getdataserver",
        data: {...requestModel.toJson(), "loading": showLoadingUI},
      );
      if (response.statusCode == 200) {
        var responseModel = ResponseModel.fromJson(response.data);
        if (responseModel.error == 0) {
          dynamic data;
          if (responseModel.data is String) {
            try {
              data = json.decode(responseModel.data as String);
            } catch (e) {
              data = responseModel.data;
            }
          } else {
            data = responseModel.data;
          }
          return data;
        } else {
          return Future.error("${responseModel.msg}");
        }
      } else {
        return Future.error("${response.statusCode}");
      }
    } catch (e) {
      return Future.error(e);
    }
  }

  download(String url, String savePath,
      {Function? onDone,
      Function(double value)? progress,
      Function? onError}) async {
    this._loading = false;
    var file = File(savePath);
    _dio.head(url).then((value) {
      return int.parse(value.headers.value(Headers.contentLengthHeader)!);
    }).then((contentLength) {
      int downloadLength = 0;
      int fileLocalLength = 0;
      if (file.existsSync()) {
        // file.deleteSync();
        fileLocalLength = file.lengthSync();
      }

      downloadLength = fileLocalLength;
      if (fileLocalLength > contentLength) {
        file.deleteSync();
        fileLocalLength = 0;
      } else if (fileLocalLength == contentLength) {
        onDone?.call();
      } else {
        _dio
            .get<ResponseBody>(url,
                options: Options(
                    responseType: ResponseType.stream,
                    headers: {"range": "bytes=$fileLocalLength-"}))
            .then((value) {
          return value.data!.stream;
        }).then((value) {
          var fileStream = file.openSync(mode: FileMode.append);

          value.listen((data) {
            fileStream.writeFromSync(data);
            downloadLength = downloadLength + data.length;
            progress?.call(downloadLength / contentLength);
          }).onDone(() {
            fileStream.close();
            onDone?.call();
          });
        }).onError((error, stackTrace) {
          Get.find<Logger>().e('下载出错:$error');
          onError?.call();
        });
      }
    }).onError((error, stackTrace) {
      Get.find<Logger>().e('下载出错:$error');
      onError?.call();
    });
  }
}
